EF Core met MySQL en forms in ASP.NET Core
Formulieren worden gebruikt voor het overbrengen van gegevens van de browser naar de webserver voor verdere verwerking, zoals het opslaan in een database. Hoe je de gegevens opvraagt uit en opslaat in een database is het onderwerp van deze les. Dat wordt ook CRUD verrichtingen genoemd, of Create, Read, Update en Delete operaties.
Video
Lesmateriaal
Lees aandachtig de volgende tutorials. Besteed vooral voldoende aandacht aan het bestuderen van LINQ!
- Learn Razor Pages, Using Forms in Razor Pages, 28/10/2020
- Saineshwar Bageri, Simple CRUD Operation with Razor Pages, 26 Sep 2017
- Entity Framework Tutorial, Linq-to-Entities Query
- Meer algemeen over LINQ: LINQ Tutorial
- Het uitgewerkte voorbeeld vind je op Bitbucket.
Updaten
We beginnen met de Updating One knop in de ReadingOne Razor Page te implementeren.
- De Bll klasse van
OrderStatus
moet er zo uitzien:using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace BiblioAdmin.Bll { public partial class OrderStatus { [Required] [Column(TypeName = "varchar(255)")] public string Name { get; set; } [Column(TypeName = "varchar(1024)")] public string Description { get; set; } [Key] [Column(TypeName = "int(11)")] public int Id { get; set; } } }
- Verwijder alle methoden uit de DBContext klasse en houdt alleen de constructors over:
using Microsoft.EntityFrameworkCore; namespace BiblioAdmin.Bll { public partial class Docent2Context : DbContext { public Docent2Context() { } public Docent2Context(DbContextOptions<Docent2Context> options) : base(options) { } public virtual DbSet<Book> Book { get; set; } public virtual DbSet<Customer> Customer { get; set; } public virtual DbSet<Order> Order { get; set; } public virtual DbSet<OrderItem> OrderItem { get; set; } public virtual DbSet<OrderStatus> OrderStatus { get; set; } public virtual DbSet<ShippingMethod> ShippingMethod { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { } } } }
- We maken een UpdatingOne.cshtml Razor Page in de map Pages/OrderStatus.
- In de
PageModel
klasse in het het code behind bestand UpdatingOne.cshtml.cs voegen we de volgende code toe:- een
DbContext
property en Constructor Injection toe:private readonly Bll.Docent2Context dbContext; // voeg constructor toe om geïnjecteerde DBContext // te kunnen binnenkrijgen in deze klasse public UpdatingOneModel(Bll.Docent2Context dbContext) { this.dbContext = dbContext; }
- een property voor een instantie van
OrderStatus
Bll klassepublic Bll.OrderStatus OrderStatus { get; set; }
- een property voor een generieke lijst met instanties van de
OrderStatus
klasse:public List<Bll.OrderStatus> OrderStatusList { get; set; }
- In de
OnGet
methode haal met behulp vandbContext
de rij uit tabel op die gewijzigd moet worden. Let erop dat deze methode nu een parameter heeft, nl. int? id. Het vraagteken geeft aan dat die optioneel is. We lezen ook alle rijen in uit de tabel:public void OnGet(int? id) { this.OrderStatus = dbContext.OrderStatus.SingleOrDefault(m => m.Id == id); OrderStatusList = dbContext.OrderStatus.ToList(); }
- Om gegevens die in het formulier zullen worden ingetypt te binden aan de instantie van de
OrderStatus
klasse, moeten we de annotatie[BindProperty]
toevoegen aan de eigenschapOrderStatus
die we daarnet gedeclareerd hebben in de klasseUpdatingOneModel
:[BindProperty] public Bll.OrderStatus OrderStatus { get; set; }
-
Tenslote moeten we een methode toevoegen om de gegevens die de gebruiker eventueel gewijzigd heeft in de database op te slagen. De gegevens worden verstuurd naar de server op het moment dat de gebruiker op de
Update
knop drukt. Dat is eensubmit
knop, dus zal er een POST request naar de server gestuurd worden. In debutton
geven we mee dat de handler voor de POSTSubmit
is. Dus de naam van de methode isonPostSubmit
.Als de gebruiker de regels niet volgt die met Data Annotations hebben opgelegd, zoals bv [Required], dan keren we terug naar de
UpdatingOne
pagina en melden de fout. Als er geen fouten werden ingetypt gaan we naar deIndex
pagina. We testen dit met de methodeModelState.IsValid
.Vermits deze methode een pagina moet retourneren moeten we als gegevenstype voor de functie
ActionResult
opgeven.public ActionResult OnPostUpdate(Bll.OrderStatus orderStatus) { if (!ModelState.IsValid) { // als er een foutief gegeven is ingetypt ga terug // de pagina en toon de fout return Page(); // return page } // dbContext.OrderStatus.Update(orderStatus); dbContext.OrderStatus.Update(orderStatus); dbContext.SaveChanges(); // keer terug naar de index pagina van OrderStatus return RedirectToPage("Index"); }
- een
- In de view, de UpdatingOne.cshtml pagina:
- declareren we eerst die
id
in de@Page
directive:@page "{id}"
- In de view, het UpdatingOne.cshtml bestand voegen we een form element met HTML controlementen toe.
- Let op het gebruik van Tag Helpers, meer over Tag Helpers:
asp-for
asp-validation
asp-page
asp-page-handler
- De view (UpdatingOne.cshtml) zelf, ziet er als volgt uit:
@page "{id}" @model BiblioAdmin.Pages.OrderStatus.UpdatingOneModel @{ } <h3>Updating OrderStatus</h3> <hr /> <br /> <form method="post"> <fieldset> <div> <label asp-for="OrderStatus.Id"></label> <input asp-for="OrderStatus.Id" /> </div> <div> <label asp-for="OrderStatus.Name"></label> <input asp-for="OrderStatus.Name" /> <span class="alert-danger" asp-validation-for="OrderStatus.Name"></span> </div> <div> <label asp-for="OrderStatus.Description"></label> <textarea asp-for="OrderStatus.Description"></textarea> </div> </fieldset> <div> <button type="submit" value="Update" asp-page-handler="Update">Update</button> </div> </form>
- Let op het gebruik van Tag Helpers, meer over Tag Helpers:
- declareren we eerst die
- Tenslotte passen we de UpdatinOne link aan in de ReadingOne.cshtml pagina:
<a href="/OrderStatus/UpdatingOne/@Model.OrderStatus.Id" class="tile"> <span class="icon-pencil"></span> <span class="screen-reader-text">Updating One</span> </a>
Delete
- Het deleten van een rij uit de tabel gebeurt vanuit de ReadingOne.cshtml pagina.
- In de view, de ReadingOne.cshtml pagina wijzigen we de link voor Delete. We gebruiken Tag Helpers om de link te laten genereren. We maken kennis met nog een Tag Helper, de
asp-route-id
:<a asp-page="./ReadingOne" onclick="return confirm('Weet je zeker dat je deze Orderstatus wilt deleten?');" asp-page-handler="Delete" asp-route-id="@Model.OrderStatus.Id">Delete</a>
- We moeten geen nieuwe Razor Page openen, het deleten van de rij in de tabel gebeurt in het code behind bestand van de ReadingOne pagina, namelijk in de
OnGetDelete
methode van deReadingOneModel
klasse:public ActionResult OnGetDelete(int? id) { if (id != null) { Bll.OrderStatus orderStatus = new Bll.OrderStatus(); orderStatus.Id = (int) id; dbContext.Remove(orderStatus); dbContext.SaveChanges(); return RedirectToPage("Index"); } return Page();
Insert
Volg dezelfde stappen als voor Update.
- Maak een nieuwe Razor Page in de map OrderStatus met de naam InsertingOne.
- Pas het model aan:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace BiblioAdmin.Pages.OrderStatus { public class InsertingOneModel : PageModel { private readonly Bll.Docent2Context dbContext; // voeg constructor toe om geïnjecteerde DBContext // te kunnen binnenkrijgen in deze klasse public InsertingOneModel(Bll.Docent2Context dbContext) { this.dbContext = dbContext; } [BindProperty] public Bll.OrderStatus OrderStatus { get; set; } public List<Bll.OrderStatus> OrderStatusList { get; set; } public void OnGet() { OrderStatusList = dbContext.OrderStatus.ToList(); } public ActionResult OnPostInsert(Bll.OrderStatus orderStatus) { if (!ModelState.IsValid) { // als er een foutief gegeven is ingetypt ga terug // de pagina en toon de fout return Page(); // return page, nog een nieuwe ingeven } // dbContext.OrderStatus.Update(orderStatus); dbContext.OrderStatus.Add(orderStatus); dbContext.SaveChanges(); // keer terug naar de index pagina van OrderStatus return RedirectToPage("Index"); } } }
- Pas de view aan:
@page @model BiblioAdmin.Pages.OrderStatus.InsertingOneModel @{ } <h3>Inserting OrderStatus</h3> <hr /> <br /> <form method="post"> <fieldset> <div> <label asp-for="OrderStatus.Name"></label> <input asp-for="OrderStatus.Name" /> <span class="alert-danger" asp-validation-for="OrderStatus.Name"></span> </div> <div> <label asp-for="OrderStatus.Description"></label> <textarea asp-for="OrderStatus.Description"></textarea> </div> </fieldset> <div> <button type="submit" value="Insert" asp-page-handler="Insert">Insert</button> </div> </form>
- Pas de InsertingOne link in de Index en de
ReadingOne
pagina aan:<a href="/OrderStatus/InsertingOne" class="tile"> <span class="icon-plus"></span> <span class="screen-reader-text">Inserting One</span> </a>
- Pas de InsertingOne link aan in de Index pagina van OrderStatus:
<a href="/OrderStatus/InsertingOne" class="tile"> <span class="icon-plus"></span> <span class="screen-reader-text">Inserting One</span> </a>
of met Tag Helpers:<a asp-page="./InsertingOne" asp-page-handler="Inserting">Inserting One </a>
Opdracht
Maak de CRUD operaties voor de volgende entiteiten (zonder rekening te houden met foreign key's):
- ShippingMethod
- OrderStatus
- Book
- Order
- OrderItem